package com.einmeer.hfbank.service.impl;

import com.einmeer.hfbank.entity.Card;
import com.einmeer.hfbank.entity.Deposit;
import com.einmeer.hfbank.entity.InterestRate;
import com.einmeer.hfbank.hfconst.DepositConst;
import com.einmeer.hfbank.mapper.CardMapper;
import com.einmeer.hfbank.mapper.DepositMapper;
import com.einmeer.hfbank.mapper.InterestRateMapper;
import com.einmeer.hfbank.service.DepositService;
import com.einmeer.hfbank.vo.ResultVo;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 芊嵛
 * @date 2024/1/13
 */

@Service
@Transactional
public class DepositServiceImpl implements DepositService {
    @Resource
    private DepositMapper depositMapper;
    @Resource
    private CardMapper cardMapper;
    @Resource
    private InterestRateMapper interestRateMapper;

    /**
     * 根据卡号和类型查询存款信息
     *
     * @param cardNumber
     * @param depositType
     * @return
     */
    @Override
    public ResultVo queryAllByCardNumber(Long cardNumber, Integer depositType) {
        List<Deposit> list = depositMapper.selectAllByCardNumber(cardNumber, depositType);
        if (list.isEmpty()) {
            return new ResultVo(DepositConst.DEPOSITDNO, DepositConst.SELECTNO);
        }
        return new ResultVo(DepositConst.DEPOSITDOK, list, DepositConst.SELECTOK);
    }

    /**
     * 存定期
     *
     * @param depositAmount
     * @param depositType
     * @param cardNumber
     * @return
     */
    @Override
    public ResultVo transformPeriodical(String depositAmount, Integer depositType, Long cardNumber) {
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        // 判断一下金额是否足够
        Card card = cardMapper.selectCard(cardNumber);
        BigDecimal a = new BigDecimal(card.getCardCurrent());
        BigDecimal b = new BigDecimal(depositAmount);
        // 取款
        // 金额不足不能转换
        if (a.compareTo(b) == -1) {
            return new ResultVo(DepositConst.DEPOSITDNO, DepositConst.BALANCENO);
        } else {
            // 排序存款列表
            List<Deposit> depositList = depositMapper.selectAllByCardNumber(cardNumber, 0);
            // 根据存款id倒序
            depositList = depositList.stream().sorted(Comparator.comparing(Deposit::getDepositId).reversed()).collect(Collectors.toList());
            // 遍历存款id
            for (Deposit temp : depositList) {
                // 取出存款金额
                BigDecimal balance = new BigDecimal(temp.getDepositAmount());
                System.out.println(temp.getDepositId() + "余额" + balance);
                // 如果b等于0直接退出
                if (b.compareTo(BigDecimal.valueOf(0)) == 0) {
                    break;
                } else if (balance.compareTo(BigDecimal.valueOf(0)) == 0) {
                    continue;
                }
                // 如果余额大于等于转为定期
                else if (balance.compareTo(b) > -1) {
                    balance = balance.subtract(b);
                    // 更新存款表,次数改为0
                    depositMapper.updateDeposit(temp.getDepositId(), balance.toPlainString(), timestamp, 0);
                    break;
                }
                // 如果余额小于转为定期
                else if (balance.compareTo(b) == -1) {
                    // 更新存款表，存款金额改为0，次数改为0
                    depositMapper.updateDeposit(temp.getDepositId(), "0", timestamp, 0);
                    // b减余额
                    b = b.subtract(balance);
                }
            }
        }
        // 存款
        int n = depositMapper.insertOne(depositAmount, depositType, timestamp, 0, cardNumber);
        if (n == 1) {
            return new ResultVo(DepositConst.DEPOSITDOK, DepositConst.INSERTOK);
        }
        return new ResultVo(DepositConst.DEPOSITDNO, DepositConst.INSERTNO);
    }

    /**
     * 查询所有定期存款
     * @param cardNumber
     * @return
     */
    @Override
    public ResultVo queryAllFroPeriodical(Long cardNumber) {
        List<Deposit> list = new ArrayList<>();
        // 查询所有类型的定期存款
        List<InterestRate> interestRateList = interestRateMapper.selectAll();
        for (InterestRate temp1 : interestRateList) {
            // 确定不是活期
            if (temp1.getIRType() != 0) {
                List<Deposit> depositList = depositMapper.selectAllByCardNumber(cardNumber, temp1.getIRType());
                for (Deposit temp2 : depositList) {
                    if (temp2 != null) {
                        // 把所有定期存款都存到list中
                        list.add(temp2);
                    }
                }
            }
        }
        // 更新定期存款
        for (Deposit deposit : list) {
            // 获取利率
            BigDecimal rate = new BigDecimal(interestRateMapper.selectByType(deposit.getDepositType()).getIRPercentage());
            // 获取几个月经行更新
            int month = interestRateMapper.selectByType(deposit.getDepositType()).getIRMonth();
            // 获得时间
            Timestamp timestamp = deposit.getDepositDate();
            long oldTime = timestamp.getTime();
            Timestamp now = new Timestamp(System.currentTimeMillis());
            long nowTime = now.getTime();
            // 时间差,相差几个月
            long afterMonth1 = (nowTime - oldTime) / 1000 / 60 / 60 / 24 / 30;
            int afterMonth2 = (int) afterMonth1;
            // 更新过几次
            int times = deposit.getDepositTimes();
            // 需要再更新几次
            int againTimes = afterMonth2 / month;
            // 获取未更新的depositAmount
            BigDecimal b = new BigDecimal(deposit.getDepositAmount());
            // 1+利率
            BigDecimal c = new BigDecimal(1);
            rate = rate.add(c);
            // 得到真实金额
            int tempAgainTimes = againTimes;
            while (tempAgainTimes != 0) {
                b = b.multiply(rate);
                tempAgainTimes--;
            }
            // 更新deposit表,前提数据更新了
            if (againTimes != 0) {
                againTimes += times;
                depositMapper.updateDeposit(deposit.getDepositId(), b.toPlainString(), now, againTimes);
            }
        }
        // 情况list
        list.clear();
        for (InterestRate temp1 : interestRateList) {
            // 确定不是活期
            if (temp1.getIRType() != 0) {
                List<Deposit> depositList = depositMapper.selectAllByCardNumber(cardNumber, temp1.getIRType());
                for (Deposit temp2 : depositList) {
                    if (temp2 != null) {
                        // 把所有定期存款都存到list中
                        list.add(temp2);
                    }
                }
            }
        }
        if (list.isEmpty()) {
            return new ResultVo(DepositConst.DEPOSITDNO, DepositConst.SELECTNO);
        }
        return new ResultVo(DepositConst.DEPOSITDOK, list, DepositConst.SELECTOK);
    }

    /**
     * 定期转活期
     * @param depositId
     * @return
     */
    @Override
    public ResultVo transformCurrent(Long depositId) {
        // 更新存款
        Deposit deposit = depositMapper.selectOne(depositId);
        if (deposit == null){
            return new ResultVo(DepositConst.DEPOSITDNO,DepositConst.UPDATENO);
        }
        // 获取利率
        BigDecimal rate = new BigDecimal(interestRateMapper.selectByType(deposit.getDepositType()).getIRPercentage());
        // 获取几个月经行更新
        int month = interestRateMapper.selectByType(deposit.getDepositType()).getIRMonth();
        // 获得时间
        Timestamp timestamp = deposit.getDepositDate();
        long oldTime = timestamp.getTime();
        Timestamp now = new Timestamp(System.currentTimeMillis());
        long nowTime = now.getTime();
        // 时间差,相差几个月
        long afterMonth1 = (nowTime - oldTime) / 1000 / 60 / 60 / 24 / 30;
        int afterMonth2 = (int) afterMonth1;
        // 更新过几次
        int times = deposit.getDepositTimes();
        // 需要再更新几次
        int againTimes = afterMonth2 / month;
        // 获取未更新的depositAmount
        BigDecimal b = new BigDecimal(deposit.getDepositAmount());
        // 1+利率
        BigDecimal c = new BigDecimal(1);
        rate = rate.add(c);
        // 得到真实金额
        int tempAgainTimes = againTimes;
        while (tempAgainTimes != 0) {
            b = b.multiply(rate);
            tempAgainTimes--;
        }
        // 更新deposit表,前提数据更新了
        if (againTimes != 0) {
            againTimes += times;
            depositMapper.updateDeposit(deposit.getDepositId(), b.toPlainString(), now, againTimes);
        }

        int n = depositMapper.updateCurrent(depositId);
        if (n==1){
            return new ResultVo(DepositConst.DEPOSITDOK,DepositConst.UPDATEOK);
        }
        return new ResultVo(DepositConst.DEPOSITDNO,DepositConst.UPDATENO);
    }
}
